package com.htpay.controller;

import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSONObject;
import com.htpay.exception.CustomException;
import com.htpay.model.common.Constant;
import com.htpay.model.common.DictConstant;
import com.htpay.model.common.ResponseBean;
import com.htpay.model.entity.Merchant;
import com.htpay.model.vo.LoginModel;
import com.htpay.service.IBaseAPIService;
import com.htpay.service.IMerchantService;
import com.htpay.util.*;
import com.htpay.util.sms.SmsHelperUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;

@RestController
@RequestMapping("/account")
@Slf4j
@Component
public class LoginController {
    @Autowired
    IMerchantService merchantService;

    @Autowired
    IBaseAPIService baseAPIService;

    /**
     * RefreshToken过期时间
     */
    @Value("${refreshTokenExpireTime}")
    private String refreshTokenExpireTime;

    @Value("${htpay.sms.maxCount}")
    private Integer smsMaxCount;

    @Value("${htpay.sms.expireTime}")
    private Integer smsExpireTime;

    @Value("${htpay.sms.platform}")
    private String smsPlatForm;

    @RequestMapping(value = "/login", method = RequestMethod.POST)
    public ResponseBean login(@RequestBody LoginModel loginModel) {
        ResponseBean bean = new ResponseBean();
        String username = loginModel.getUsername();
        String password = loginModel.getPassword();
        if (ObjectConvertUtils.isEmpty(username)) {
            return bean.error("用户名不能为空");
        }
        if (ObjectConvertUtils.isEmpty(password)) {
            return bean.error("密码不能为空");
        }
        if (ObjectConvertUtils.isEmpty(loginModel.getCaptcha())) {
            return bean.error("验证code不能为空");
        }
        if (ObjectConvertUtils.isEmpty(loginModel.getCheckKey())) {
            return bean.error("验证码key不能为空");
        }

        //update for：暂时注释掉密码加密逻辑，有点问题
        //前端密码加密，后端进行密码解密
        //password = AesEncryptUtil.desEncrypt(sysLoginModel.getPassword().replaceAll("%2B", "\\+")).trim();//密码解密
        //update for：暂时注释掉密码加密逻辑，有点问题

        Object checkCode = JedisUtil.getObject(loginModel.getCheckKey());
        if (checkCode == null) {
            return bean.error("验证码失效");
        }

        //update 校验验证码
        if (!checkCode.equals(loginModel.getCaptcha())) {
            JedisUtil.delKey(loginModel.getCheckKey());
            return bean.error("验证码错误");
        }

        //1. 校验用户是否有效
        Merchant merchant = merchantService.getUserByName(username);
        ResponseBean bean1 = merchantService.checkUserIsEffective(merchant);
        if (!bean1.getCode().equals(Constant.BUSI_SUCC_CODE)) {
            return bean1;
        }

        //2. 校验用户名或密码是否正确
        String userPassword = PasswordUtil.encrypt(username, password, merchant.getSalt());
        String passWord = merchant.getPassword();
        if (!passWord.equals(userPassword)) {
            JedisUtil.delKey(loginModel.getCheckKey());
            log.info("password===[" + passWord + "]===userPassword===[" + userPassword + "]");
            return bean.error("用户名或密码错误");
        }

        //用户登录信息
        bean = userInfo(merchant, bean);
        baseAPIService.addLog("用户名: " + username + ",登录成功！", DictConstant.LOG_TYPE_1, null);

        return bean;
    }

    /**
     * 用户信息
     *
     * @param merchant
     * @param bean
     * @return
     */
    private ResponseBean userInfo(Merchant merchant, ResponseBean bean) {
        String username = merchant.getLoginName();

        // 生成token
        String currentTimeMillis = String.valueOf(System.currentTimeMillis());
        String token = JwtUtil.sign(username, currentTimeMillis);

        // 设置token当前current time字段缓存有效时间
        JedisUtil.setObject(Constant.PREFIX_SHIRO_REFRESH_TOKEN + username, currentTimeMillis, Integer.parseInt(refreshTokenExpireTime));
        // 将商户ID信息存储到redis中
        JedisUtil.setObject(Constant.SYS_USER_INFO + username, merchant.getMerchantId(), Integer.parseInt(refreshTokenExpireTime));

        // 获取用户信息
        JSONObject obj = new JSONObject();
        obj.put("token", token);
        obj.put("userInfo", merchant);

        bean.setCode(Constant.BUSI_SUCC_CODE);
        bean.setMsg("登录成功");
        bean.setData(obj);
        return bean;
    }

    /**
     * 获取校验码
     */
    @GetMapping(value = "/getCheckCode")
    public ResponseBean getCheckCode() {
        ResponseBean bean = new ResponseBean();
        Map<String, String> map = new HashMap<String, String>();
        try {
            String code = RandomUtil.randomString(Constant.BASE_CHECK_CODES, 4);
            String key = MD5Util.MD5Encode(code + System.currentTimeMillis(), "utf-8");
            //验证码过期时间为60s
            JedisUtil.setObject(key, code, 60);

            map.put("key", key);
            map.put("code", code);
            log.info("==== 创建验证码成功：" + code + " ====");
            bean.success("获取验证码成功", map);
        } catch (Exception e) {
            e.printStackTrace();
            bean.error("获取验证码失败");
        }
        return bean;
    }

    /**
     * 退出登录
     *
     * @param request
     * @param response
     * @return
     */
    @RequestMapping(value = "/logout", method = RequestMethod.GET)
    public ResponseBean logout(HttpServletRequest request, HttpServletResponse response) {
        //用户退出逻辑
        String token = request.getHeader(Constant.X_ACCESS_TOKEN);
        if (ObjectConvertUtils.isEmpty(token)) {
            log.info("请求地址IP【" + IPUtils.getIpAddr(request) + "】退出失败，request请求头部X_ACCESS_TOKEN为空!");
            return new ResponseBean(Constant.BUSI_ERROR_COD, "退出登录失败！", null);
        }

        String username = JwtUtil.getClaim(token, Constant.ACCOUNT);
        Merchant merchant = baseAPIService.getUserByName(username);
        if (merchant != null) {
            baseAPIService.addLog("用户名: " + merchant.getLoginName() + ",退出成功！", DictConstant.LOG_TYPE_1, null);
            log.info(" 用户名:  " + merchant.getLoginName() + ",退出成功！ ");
            //清空用户登录Token缓存
            JedisUtil.delKey(Constant.PREFIX_SHIRO_REFRESH_TOKEN + username);
            //清空商户ID信息
            JedisUtil.delKey(Constant.SYS_USER_INFO + username);

            return new ResponseBean(Constant.BUSI_SUCC_CODE, "退出登录成功！", null);
        } else {
            return new ResponseBean(Constant.BUSI_ERROR_COD, "Token无效！", null);
        }
    }

    /**
     * 短信登录接口: 可以根据模板动态区分不同功能的接口
     * smsmode 短信模板方式  0 .登录模板、1.注册模板、2.密码重置
     *
     * @param jsonObject
     * @return
     */
    @PostMapping(value = "/sms/send")
    public ResponseBean sms(@RequestBody JSONObject jsonObject) {
        ResponseBean bean = new ResponseBean();

        String mobile = jsonObject.getString("mobile");
        if (ObjectConvertUtils.isEmpty(mobile)) {
            return bean.error("手机号为必传字段");
        }

        if (mobile.length() != 11) {
            return bean.error("手机号不是标准11位");
        }

        String smsMode = jsonObject.getString("smsmode");
        if (ObjectConvertUtils.isEmpty(smsMode)) {
            return bean.error("短信模板为必传字段");
        }

        log.info("========= 手机号：" + mobile + "正在请求sms短信接口 ======");

        //有效期内
        Object object = JedisUtil.getObject(mobile);
        if (object != null) {
            log.info("手机号：" + mobile + "验证码6分钟内，仍然有效");
            return new ResponseBean(Constant.BUSI_ERROR_COD, "验证码6分钟内，仍然有效！", null);
        }

        //限制统一手机号当天只能发送20次短信验证码
        String nowYmd = DateUtils.getDataString(DateUtils.date_sdf);
        String msgCodeCountKey = nowYmd + ":getMsgCodeCount:" + mobile;
        Object smsSendCount = JedisUtil.getObject(msgCodeCountKey);
        if (smsSendCount != null) {
            Integer msgCount = (Integer) smsSendCount;
            if (msgCount > smsMaxCount) {
                log.info("手机号：" + mobile + "获取短信次数超限,最大次数为【" + smsMaxCount + "】次/小时");
                return new ResponseBean(Constant.BUSI_ERROR_COD, "获取短信次数超限!", null);
            }
        }

        //随机数
        String captcha = RandomUtil.randomNumbers(6);
        JSONObject obj = new JSONObject();
        obj.put("code", captcha);
        try {
            boolean sendStatus = false;
            Merchant merchant = merchantService.getUserByPhone(mobile);
            //注册模板
            if (DictConstant.SMS_TPL_TYPE_1.equals(smsMode)) {
                if (merchant != null) {
                    baseAPIService.addLog("手机号已经注册，请直接登录！", DictConstant.LOG_TYPE_1, null);
                    return new ResponseBean(Constant.BUSI_ERROR_COD, "手机号已经注册，请直接登录！", null);
                }
            } else {
                //登录模式，校验用户有效性
                bean = merchantService.checkUserIsEffective(merchant);
                if (!bean.getCode().equals(Constant.BUSI_SUCC_CODE)) {
                    return bean;
                }
            }

            //调用发送短信接口
            sendStatus = SmsHelperUtil.send(mobile, captcha, smsPlatForm);

            if (!sendStatus) {
                return new ResponseBean(Constant.BUSI_ERROR_COD, "短信验证码发送失败,请稍后重试", null);
            }

            //验证码10分钟内有效
            JedisUtil.setObject(mobile, captcha, smsExpireTime);

            //限制1小时内一个手机号20条短信
            Object c = JedisUtil.getObject(msgCodeCountKey);
            int count = 0;
            if (c != null) {
                count = Integer.parseInt(c.toString());
            }
            JedisUtil.setObject(msgCodeCountKey, count + 1, 3600);

            bean = new ResponseBean(Constant.BUSI_SUCC_CODE, "短信验证码已发送", null);
        } catch (Exception e) {
            e.printStackTrace();
            throw new CustomException("调用短信网关异常:" + e.getMessage());
        }

        return bean;
    }
}
